/*
 * @Author: 0x9DEFA478
 * @Date: 2021-07-27 17:08:48
 * @LastEditTime: 2021-07-27 23:08:14
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "W25Q128_sim.h"
#include "IP_GPIO.h"






#define W25Q_sim_CS_GPIOx       GPIOB
#define W25Q_sim_SCK_GPIOx      GPIOB
#define W25Q_sim_MOSI_GPIOx     GPIOC
#define W25Q_sim_MISO_GPIOx     GPIOC


#define W25Q_sim_CS_PinNum      6
#define W25Q_sim_SCK_PinNum     2
#define W25Q_sim_MOSI_PinNum    9
#define W25Q_sim_MISO_PinNum    10


#define W25Q_sim_CS_High()         do{W25Q_sim_CS_Delay();oIP_GPIO_SetOutput_High(W25Q_sim_CS_GPIOx,W25Q_sim_CS_PinNum);}while(0)
#define W25Q_sim_CS_Low()          oIP_GPIO_SetOutput_Low(W25Q_sim_CS_GPIOx,W25Q_sim_CS_PinNum)

#define W25Q_sim_SCK_High()        oIP_GPIO_SetOutput_High(W25Q_sim_SCK_GPIOx,W25Q_sim_SCK_PinNum)
#define W25Q_sim_SCK_Low()         oIP_GPIO_SetOutput_Low(W25Q_sim_SCK_GPIOx,W25Q_sim_SCK_PinNum)


#define W25Q_sim_MOSI_High()       oIP_GPIO_SetOutput_High(W25Q_sim_MOSI_GPIOx,W25Q_sim_MOSI_PinNum)
#define W25Q_sim_MOSI_Low()        oIP_GPIO_SetOutput_Low(W25Q_sim_MOSI_GPIOx,W25Q_sim_MOSI_PinNum)

#define W25Q_sim_MISO_Bit()        oIP_GPIO_GetInputBit(W25Q_sim_MISO_GPIOx,W25Q_sim_MISO_PinNum)


static void W25Q_sim_CS_Delay(){
  //CS无效要大于10ns 对于 如果是擦除 要大于50ns

  __NOP();
  __NOP();
  __NOP();
  __NOP();
}

static unsigned char W25Q_sim_TxRxByte(unsigned char txData){

	unsigned char mask;
	unsigned char rxData;

	mask=0x80;
	while(mask){
		
		if(mask&txData){
			W25Q_sim_MOSI_High();
		}
		else{
			W25Q_sim_MOSI_Low();
		}

		W25Q_sim_SCK_High();

		if(W25Q_sim_MISO_Bit()){
			rxData|=mask;
		}
		else{
			rxData&=(~mask);
		}

		W25Q_sim_SCK_Low();
	
		mask>>=1;
	}

	return rxData;
}

static void W25Q_sim_TxRx(unsigned char *src,unsigned char *dst,unsigned int Len){

	while(Len)
	{
		Len--;

		*dst=W25Q_sim_TxRxByte(*src);
		src++;
		dst++;
	}
}

static void W25Q_sim_IOInit(){

	RCC->AHB1ENR|=RCC_AHB1ENR_GPIOBEN;
	RCC->AHB1ENR|=RCC_AHB1ENR_GPIOCEN;
	
	//SpiFlash
  GPIOD->BSRR=1<<0;
  oIP_GPIO_Config(W25Q_sim_CS_GPIOx,W25Q_sim_CS_PinNum,vIP_GPIO_Mode_OUT,vIP_GPIO_OutType_PP,vIP_GPIO_Speed_MEDIUM,vIP_GPIO_PuPd_NP);
  oIP_GPIO_Config(W25Q_sim_SCK_GPIOx,W25Q_sim_SCK_PinNum,vIP_GPIO_Mode_OUT,vIP_GPIO_OutType_PP,vIP_GPIO_Speed_MEDIUM,vIP_GPIO_PuPd_NP);
  oIP_GPIO_Config(W25Q_sim_MOSI_GPIOx,W25Q_sim_MOSI_PinNum,vIP_GPIO_Mode_OUT,vIP_GPIO_OutType_PP,vIP_GPIO_Speed_MEDIUM,vIP_GPIO_PuPd_NP);
  oIP_GPIO_Config(W25Q_sim_MISO_GPIOx,W25Q_sim_MISO_PinNum,vIP_GPIO_Mode_IN,vIP_GPIO_OutType_PP,vIP_GPIO_Speed_MEDIUM,vIP_GPIO_PuPd_NP);

	W25Q_sim_CS_High();
	W25Q_sim_SCK_Low();
}



/**
 * @brief 初始化W25Q
 * @return 无
 */
void W25Q_sim_Init(){

	W25Q_sim_IOInit();
	//W25Q_sim_SetQuad();
}

/**
 * @brief 读取状态寄存器1
 * @return 无
 */
unsigned char W25Q_sim_GetStatusReg1(){
	volatile unsigned char readData=0;

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_ReadREG_Status1);
	readData=W25Q_sim_TxRxByte(0xFFU);
	W25Q_sim_CS_High();

	return (unsigned char)readData;
}

/**
 * @brief 读取状态寄存器2
 * @return 无
 */
unsigned char W25Q_sim_GetStatusReg2(){
	volatile unsigned char readData=0;

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_ReadREG_Status2);
	readData=W25Q_sim_TxRxByte(0xFFU);
	W25Q_sim_CS_High();

	return (unsigned char)readData;
}

/**
 * @brief 读取状态寄存器3
 * @return 无
 */
unsigned char W25Q_sim_GetStatusReg3(){
	volatile unsigned char readData=0;

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_ReadREG_Status3);
	readData=W25Q_sim_TxRxByte(0xFFU);
	W25Q_sim_CS_High();

	return (unsigned char)readData;
}


/**
 * @brief 状态寄存器写使能
 * @return 无
 */
void W25Q_sim_RegWriteEnable(){

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_StatusREGWriteEnable);
	W25Q_sim_CS_High();
}

/**
 * @brief 写使能
 * @return 无
 */
void W25Q_sim_WriteEnable(){

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_WriteEnable);
	W25Q_sim_CS_High();
}

/**
 * @brief 等待忙碌
 * @return 无
 */
void W25Q_sim_WaitBusy(){

	while(vW25Q_Status_BUSY&W25Q_sim_GetStatusReg1()){
		//等待BUSY为0
	}
}


/**
 * @brief 写状态寄存器1
 * @return 无
 */
void W25Q_sim_SetStatusReg1(unsigned char value){

	W25Q_sim_WaitBusy();

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_WriteREG_Status1);
	W25Q_sim_TxRxByte(value);
	W25Q_sim_CS_High();
}

/**
 * @brief 写状态寄存器2
 * @return 无
 */
void W25Q_sim_SetStatusReg2(unsigned char value){

	W25Q_sim_WaitBusy();

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_WriteREG_Status2);
	W25Q_sim_TxRxByte(value);
	W25Q_sim_CS_High();
}

/**
 * @brief 写状态寄存器3
 * @return 无
 */
void W25Q_sim_SetStatusReg3(unsigned char value){

	W25Q_sim_WaitBusy();

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_WriteREG_Status3);
	W25Q_sim_TxRxByte(value);
	W25Q_sim_CS_High();
}

/**
 * @brief 设置为quad模式
 * @return 无
 */
void W25Q_sim_SetQuad(){

	if((vW25Q_Status_QE&W25Q_sim_GetStatusReg2())==vW25Q_Status_QE){

	}else{
		W25Q_sim_WriteEnable();
		W25Q_sim_SetStatusReg2(vW25Q_Status_QE);
	}
	if((vW25Q_Status_DRV1|vW25Q_Status_DRV1)&W25Q_sim_GetStatusReg3()){
		W25Q_sim_WriteEnable();
		W25Q_sim_SetStatusReg3(0);
	}
}

/**
 * @brief 获取ID
 * @return 16位ID
 */
unsigned short W25Q_sim_GetID(){
	unsigned int driver_W25Q16_ID=0;


	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_Get_ID);
	W25Q_sim_TxRxByte(0x00);
	W25Q_sim_TxRxByte(0x00);
	W25Q_sim_TxRxByte(0x00);
	W25Q_sim_TxRx((unsigned char*)&driver_W25Q16_ID,(unsigned char*)&driver_W25Q16_ID,2);

	driver_W25Q16_ID=((short)((unsigned char)(driver_W25Q16_ID>>8)))|((unsigned short)(driver_W25Q16_ID<<8));
	return (unsigned short)driver_W25Q16_ID;
}

/**
 * @brief 获取容量
 * @return flash大小
 */
int W25Q_sim_GetSize(){

	unsigned short id;

	W25Q_sim_WaitBusy();
	id=W25Q_sim_GetID();

	if(id==vW25Q_ID_80){
		return 1024*1024;
	}else if(id==vW25Q_ID_16){
		return 2*1024*1024;
	}else if(id==vW25Q_ID_32){
		return 4*1024*1024;
	}else if(id==vW25Q_ID_64){
		return 8*1024*1024;
	}else if(id==vW25Q_ID_128){
		return 16*1024*1024;
	}else{
		return 0xFFFFFFFF;
	}
}








/**
 * @brief 读数据
 * @param W25qADDR 读取的地址
 * @param Dst 读取到的缓冲区的指针
 * @param Len 读取长度
 * @return 无
 */
void W25Q_sim_ReadData(unsigned int W25qADDR,unsigned char *Dst,int Len){

	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_FastReadData);//发送指令
	W25Q_sim_TxRxByte(W25qADDR>>16);
	W25Q_sim_TxRxByte(W25qADDR>>8);
	W25Q_sim_TxRxByte(W25qADDR);
	W25Q_sim_TxRxByte(0xFFU);

	W25Q_sim_TxRx(Dst,Dst,Len);
	W25Q_sim_CS_High();

}


/**
 * @brief 写数据
 * @param W25qADDR 写入的地址
 * @param Src 要写入的数据的指针
 * @param Len 写入长度
 * @return 无
 */
void W25Q_sim_PageProgram(unsigned int W25qADDR,unsigned char *Src,int Len){

	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_WriteEnable();
	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_PageProgram);//发送指令
	W25Q_sim_TxRxByte(W25qADDR>>16);
	W25Q_sim_TxRxByte(W25qADDR>>8);
	W25Q_sim_TxRxByte(W25qADDR);
	W25Q_sim_TxRx(Src,Src,Len);
	W25Q_sim_CS_High();
}


/**
 * @brief 擦除 4096字节
 * @param W25qADDR 要擦除扇区的地址
 * @return 无
 */
void W25Q_sim_Erase(unsigned int W25qADDR){
	
	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_WriteEnable();
	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_SectorErase);//发送指令
	W25Q_sim_TxRxByte(W25qADDR>>16);
	W25Q_sim_TxRxByte(W25qADDR>>8);
	W25Q_sim_TxRxByte(W25qADDR);
	W25Q_sim_CS_High();
}

/**
 * @brief 擦除 32*1024字节
 * @param W25qADDR 要擦除扇区的地址
 * @return 无
 */
void W25Q_sim_32KBErase(unsigned int W25qADDR){

	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_WriteEnable();
	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_TxRxByte(vW25Q_CMD_32KBErase);//发送指令
	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(W25qADDR>>16);
	W25Q_sim_TxRxByte(W25qADDR>>8);
	W25Q_sim_TxRxByte(W25qADDR);
	W25Q_sim_CS_High();
}

/**
 * @brief 擦除 64*1024字节
 * @param W25qADDR 要擦除扇区的地址
 * @return 无
 */
void W25Q_sim_64KBErase(unsigned int W25qADDR){

	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_WriteEnable();
	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_64KBErase);//发送指令
	W25Q_sim_TxRxByte(W25qADDR>>16);
	W25Q_sim_TxRxByte(W25qADDR>>8);
	W25Q_sim_TxRxByte(W25qADDR);
	W25Q_sim_CS_High();
}

/**
 * @brief 全片擦除 等待结束
 * @return 无
 */
void W25Q_sim_ChipErase(){

	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_WriteEnable();
	W25Q_sim_WaitBusy();//wait...
	W25Q_sim_CS_Low();
	W25Q_sim_TxRxByte(vW25Q_CMD_ChipErase);//发送指令
	W25Q_sim_CS_High();
	W25Q_sim_WaitBusy();//wait...
}








